package com.cy.hui_jie_dan.service.impl;

import com.cy.hui_jie_dan.popj.entity.ChatMessage;
import com.cy.hui_jie_dan.service.ChatMessageService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ChatMessageServiceImpl implements ChatMessageService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private static final ObjectMapper objectMapper = new ObjectMapper();
    private static final long MESSAGE_EXPIRATION = 30 * 24 * 60 * 60; // 30 days in seconds

    static {
        // Configure ObjectMapper to support Java 8 Date and Time types
        objectMapper.registerModule(new JavaTimeModule());
        // Disable writing dates as timestamps if needed (consistent with RedisConfiguration)
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    }

    @Override
    @Transactional
    public void saveMessage(ChatMessage message) {
        try {
            message.setStatus(0); // 设置初始状态为未读
            message.setCreateTime(Instant.now());
            message.setUpdateTime(Instant.now());
            message.setMessageId(UUID.randomUUID().toString());

            // 保存消息到Redis
            String messageJson = objectMapper.writeValueAsString(message);
            redisTemplate.opsForValue().set(message.getMessageKey(), messageJson, MESSAGE_EXPIRATION, java.util.concurrent.TimeUnit.SECONDS);

            // 添加到历史记录列表
            redisTemplate.opsForList().rightPush(message.getHistoryKey(), messageJson);
            redisTemplate.expire(message.getHistoryKey(), MESSAGE_EXPIRATION, java.util.concurrent.TimeUnit.SECONDS);

            // 更新未读消息计数
            String unreadKey = message.getUnreadKey();
            redisTemplate.opsForValue().increment(unreadKey);
            redisTemplate.expire(unreadKey, MESSAGE_EXPIRATION, java.util.concurrent.TimeUnit.SECONDS);
        } catch (JsonProcessingException e) {
            log.error("保存消息到Redis失败: {}", e.getMessage());
            throw new RuntimeException("保存消息失败", e);
        }
    }

    @Override
    public List<ChatMessage> getChatHistory(Integer userId1, Integer userId2, Integer limit, String startTime) {
        String historyKey = "chat:history:" + userId1 + ":" + userId2;
        List<Object> messages = redisTemplate.opsForList().range(historyKey, 0, limit - 1);
        
        return messages.stream()
                .map(msg -> {
                    try {
                        return objectMapper.readValue(msg.toString(), ChatMessage.class);
                    } catch (JsonProcessingException e) {
                        log.error("解析消息失败: {}", e.getMessage());
                        return null;
                    }
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void markMessageAsRead(Integer toUserId, Integer fromUserId) {
        String unreadKey = "chat:unread:" + toUserId + ":" + fromUserId;
        redisTemplate.delete(unreadKey);
    }

    @Override
    public int getUnreadMessageCount(Integer userId) {
        String pattern = "chat:unread:" + userId + ":*";
        Set<String> keys = redisTemplate.keys(pattern);
        return keys.stream()
                .mapToInt(key -> {
                    Object count = redisTemplate.opsForValue().get(key);
                    return count != null ? Integer.parseInt(count.toString()) : 0;
                })
                .sum();
    }

    @Override
    @Transactional
    public void deleteMessage(String messageId, Integer userId) {
        ChatMessage message = getMessageById(messageId);
        if (message != null && (message.getFromUserId().equals(userId) || message.getToUserId().equals(userId))) {
            message.setStatus(2); // 标记为已删除
            try {
                String messageJson = objectMapper.writeValueAsString(message);
                redisTemplate.opsForValue().set(message.getMessageKey(), messageJson, MESSAGE_EXPIRATION, java.util.concurrent.TimeUnit.SECONDS);
            } catch (JsonProcessingException e) {
                log.error("更新消息状态失败: {}", e.getMessage());
            }
        }
    }

    @Override
    public ChatMessage getMessageById(String messageId) {
        String messageKey = "chat:message:" + messageId;
        Object messageJson = redisTemplate.opsForValue().get(messageKey);
        if (messageJson != null) {
            try {
                return objectMapper.readValue(messageJson.toString(), ChatMessage.class);
            } catch (JsonProcessingException e) {
                log.error("解析消息失败: {}", e.getMessage());
            }
        }
        return null;
    }

    @Override
    public List<ChatMessage> getUnreadMessages(Integer userId) {
        String pattern = "chat:unread:" + userId + ":*";
        Set<String> keys = redisTemplate.keys(pattern);
        List<ChatMessage> messages = new ArrayList<>();
        
        for (String key : keys) {
            String[] parts = key.split(":");
            Integer fromUserId = Integer.parseInt(parts[3]);
            String historyKey = "chat:history:" + fromUserId + ":" + userId;
            List<Object> history = redisTemplate.opsForList().range(historyKey, 0, -1);
            
            if (history != null) {
                history.stream()
                        .map(msg -> {
                            try {
                                return objectMapper.readValue(msg.toString(), ChatMessage.class);
                            } catch (JsonProcessingException e) {
                                return null;
                            }
                        })
                        .filter(msg -> msg != null && msg.getStatus() == 0)
                        .forEach(messages::add);
            }
        }
        
        return messages;
    }

    @Override
    @Transactional
    public void markMessagesAsRead(List<String> messageIds, Integer userId) {
        for (String messageId : messageIds) {
            ChatMessage message = getMessageById(messageId);
            if (message != null && message.getToUserId().equals(userId)) {
                message.setStatus(1);
                try {
                    String messageJson = objectMapper.writeValueAsString(message);
                    redisTemplate.opsForValue().set(message.getMessageKey(), messageJson, MESSAGE_EXPIRATION, java.util.concurrent.TimeUnit.SECONDS);
                } catch (JsonProcessingException e) {
                    log.error("更新消息状态失败: {}", e.getMessage());
                }
            }
        }
    }

    @Override
    public int getUnreadMessageCountWithUser(Integer userId, Integer contactId) {
        String unreadKey = "chat:unread:" + userId + ":" + contactId;
        Object count = redisTemplate.opsForValue().get(unreadKey);
        return count != null ? Integer.parseInt(count.toString()) : 0;
    }

    @Override
    public List<ChatMessage> searchMessages(Integer userId, String keyword) {
        String pattern = "chat:history:*" + userId + "*";
        Set<String> keys = redisTemplate.keys(pattern);
        List<ChatMessage> results = new ArrayList<>();
        
        for (String key : keys) {
            List<Object> messages = redisTemplate.opsForList().range(key, 0, -1);
            if (messages != null) {
                messages.stream()
                        .map(msg -> {
                            try {
                                return objectMapper.readValue(msg.toString(), ChatMessage.class);
                            } catch (JsonProcessingException e) {
                                return null;
                            }
                        })
                        .filter(msg -> msg != null && msg.getContent().contains(keyword))
                        .forEach(results::add);
            }
        }
        
        return results;
    }

    @Override
    @Transactional
    public int deleteExpiredMessages(Instant cutoffDate) {
        String pattern = "chat:message:*";
        Set<String> keys = redisTemplate.keys(pattern);
        int count = 0;
        
        for (String key : keys) {
            Object messageJson = redisTemplate.opsForValue().get(key);
            if (messageJson != null) {
                try {
                    ChatMessage message = objectMapper.readValue(messageJson.toString(), ChatMessage.class);
                    if (message.getCreateTime().isBefore(cutoffDate)) {
                        redisTemplate.delete(key);
                        count++;
                    }
                } catch (JsonProcessingException e) {
                    log.error("解析消息失败: {}", e.getMessage());
                }
            }
        }
        
        return count;
    }

    @Override
    @Transactional
    public boolean recallMessage(String messageId, Integer userId) {
        ChatMessage message = getMessageById(messageId);
        if (message != null && message.getFromUserId().equals(userId)) {
            if (message.getCreateTime().plusSeconds(3600).isBefore(Instant.now())) {
                return false;
            }
            
            message.setStatus(3);
            message.setRecalled(true);
            message.setUpdateTime(Instant.now());
            
            try {
                String messageJson = objectMapper.writeValueAsString(message);
                redisTemplate.opsForValue().set(message.getMessageKey(), messageJson, MESSAGE_EXPIRATION, java.util.concurrent.TimeUnit.SECONDS);
                return true;
            } catch (JsonProcessingException e) {
                log.error("撤回消息失败: {}", e.getMessage());
            }
        }
        return false;
    }

    @Override
    public List<ChatMessage> getLastMessages(Integer userId) {
        String pattern = "chat:history:*" + userId + "*";
        Set<String> keys = redisTemplate.keys(pattern);
        List<ChatMessage> lastMessages = new ArrayList<>();
        
        for (String key : keys) {
            Object lastMessage = redisTemplate.opsForList().index(key, -1);
            if (lastMessage != null) {
                try {
                    ChatMessage message = objectMapper.readValue(lastMessage.toString(), ChatMessage.class);
                    lastMessages.add(message);
                } catch (JsonProcessingException e) {
                    log.error("解析消息失败: {}", e.getMessage());
                }
            }
        }
        
        return lastMessages.stream()
                .sorted(Comparator.comparing(ChatMessage::getCreateTime).reversed())
                .collect(Collectors.toList());
    }
}